﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using YArchitech.DataModel;
using YArchitech.LIB;
using YArchitech.Revit;
using YArchitech.Revit.Electric.Common;
using YJKArch.Utils;
using RegionSplittor.Utils;
using RegionSplittor.Utils.XDataUtils;

namespace LightingEquipmentLay.Utility
{
	public static class Common
	{
		public static List<T> GetSpecifyElements<T>(Autodesk.Revit.DB.Document doc)
		{
			Type typeFromHandle = typeof(T);
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeFromHandle);
			return filteredElementCollector.Cast<T>().ToList<T>();
		}

		public static bool GetUpMostNearLevel(Autodesk.Revit.DB.Document doc, double dPrjElevation, out Level outLevel)
		{
			bool result = false;
			try
			{
				List<Level> specifyElements = Common.GetSpecifyElements<Level>(doc);
				SortedDictionary<double, Level> sortedDictionary = new SortedDictionary<double, Level>();
				foreach (Level level in specifyElements)
				{
					double projectElevation = level.ProjectElevation;
					if (projectElevation > dPrjElevation - 0.0001)
					{
						double key = Math.Abs(projectElevation - dPrjElevation);
						if (!sortedDictionary.ContainsKey(key))
						{
							sortedDictionary.Add(key, level);
						}
					}
				}
				if (sortedDictionary.Count > 0)
				{
					outLevel = sortedDictionary.First<KeyValuePair<double, Level>>().Value;
					result = true;
				}
				else
				{
					outLevel = null;
				}
			}
			catch
			{
				outLevel = null;
			}
			return result;
		}

		public static List<DetailCurve> GetDetailCurvesByTypeName(Autodesk.Revit.DB.Document doc, Level level, string strTypeName)
		{
			List<DetailCurve> list = new List<DetailCurve>();
			double projectElevation = level.ProjectElevation;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(CurveElement));
			foreach (Element element in filteredElementCollector)
			{
				DetailCurve detailCurve = ((CurveElement)element) as DetailCurve;
				if (detailCurve != null && (detailCurve.LineStyle as GraphicsStyle).Name == strTypeName)
				{
					Curve geometryCurve = detailCurve.GeometryCurve;
					if (geometryCurve.IsBound)
					{
						XYZ endPoint = geometryCurve.GetEndPoint(0);
						XYZ endPoint2 = geometryCurve.GetEndPoint(1);
						XYZ xyz = (endPoint + endPoint2) * 0.5;
						if (Geometry.IsEqual(projectElevation, xyz.Z))
						{
							list.Add(detailCurve);
						}
					}
				}
			}
			return list;
		}

		public static List<DetailCurve> GetDetailCurvesByExtendName(Autodesk.Revit.DB.Document doc, Level level, string strExtendName)
		{
			List<DetailCurve> list = new List<DetailCurve>();
			double projectElevation = level.ProjectElevation;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(CurveElement));
			foreach (Element element in filteredElementCollector)
			{
				DetailCurve detailCurve = ((CurveElement)element) as DetailCurve;
				if (detailCurve != null && LaneLineXDataManager.ReadXData(detailCurve) == strExtendName)
				{
					Curve geometryCurve = detailCurve.GeometryCurve;
					if (geometryCurve.IsBound)
					{
						XYZ endPoint = geometryCurve.GetEndPoint(0);
						XYZ endPoint2 = geometryCurve.GetEndPoint(1);
						XYZ xyz = (endPoint + endPoint2) * 0.5;
						if (Geometry.IsEqual(projectElevation, xyz.Z))
						{
							list.Add(detailCurve);
						}
					}
				}
			}
			return list;
		}

		public static double SignedDistanceTo(this Plane plane, XYZ p)
		{
			XYZ xyz = p - plane.Origin;
			return plane.Normal.DotProduct(xyz);
		}

		public static XYZ GetCurveNormal(Curve curve)
		{
			IList<XYZ> list = curve.Tessellate();
			int count = list.Count;
			XYZ xyz = list[0];
			XYZ xyz2 = list[count - 1] - xyz;
			XYZ xyz3 = null;
			if (2 == count)
			{
				XYZ xyz4 = (Math.Abs(xyz2.X) + Math.Abs(xyz2.Y) > 1E-06) ? XYZ.BasisZ : XYZ.BasisY;
				xyz3 = xyz2.CrossProduct(xyz4).Normalize();
			}
			else
			{
				int num = 0;
				while (++num < count - 1)
				{
					XYZ xyz4 = list[num] - xyz;
					xyz3 = xyz2.CrossProduct(xyz4);
					if (!xyz3.IsZeroLength())
					{
						xyz3 = xyz3.Normalize();
						break;
					}
				}
			}
			return xyz3;
		}

		public static XYZ ProjectOnto(Plane plane, XYZ p)
		{
			double num = plane.SignedDistanceTo(p);
			return p - num * plane.Normal;
		}

		public static Curve GetProjectSegCurve(Plane plane, Curve cv)
		{
			if (cv is Line)
			{
				XYZ xyz = cv.GetEndPoint(0);
				XYZ xyz2 = cv.GetEndPoint(1);
				xyz = Common.ProjectOnto(plane, xyz);
				xyz2 = Common.ProjectOnto(plane, xyz2);
				return Line.CreateBound(xyz, xyz2);
			}
			if (cv is Arc)
			{
				XYZ xyz3 = cv.GetEndPoint(0);
				XYZ xyz4 = cv.GetEndPoint(1);
				double parameter = cv.Project(xyz3).Parameter;
				double parameter2 = cv.Project(xyz4).Parameter;
				double num = (parameter + parameter2) * 0.5;
				XYZ xyz5 = cv.Evaluate(num, false);
				xyz3 = Common.ProjectOnto(plane, xyz3);
				xyz4 = Common.ProjectOnto(plane, xyz4);
				xyz5 = Common.ProjectOnto(plane, xyz5);
				return Arc.Create(xyz3, xyz4, xyz5);
			}
			return null;
		}

		public static DetailCurve AddDetailCurve2View(Autodesk.Revit.DB.Document doc, Curve cv, GraphicsStyle lineStyle = null, Autodesk.Revit.DB.View view = null)
		{
			DetailCurve detailCurve = null;
			Transaction transaction = new Transaction(doc, "CreateDtCv");
			try
			{
				transaction.Start();
				detailCurve = doc.Create.NewDetailCurve((view == null) ? doc.ActiveView : view, cv);
				if (lineStyle != null)
				{
					detailCurve.LineStyle = lineStyle;
				}
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
			}
			return detailCurve;
		}

        public static GraphicsStyle GetLineStyle(Autodesk.Revit.DB.Document doc, string strLineTypeName, Autodesk.Revit.DB.Color color, int iLineWeight = 5)
		{
			Category category = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines);
			if (category == null)
			{
				return null;
			}
			if (!category.SubCategories.Contains(strLineTypeName))
			{
				Transaction transaction = new Transaction(doc, "new line style");
				try
				{
					transaction.Start();
					Category category2 = doc.Settings.Categories.NewSubcategory(category, strLineTypeName);
					category2.LineColor = color;
					category2.SetLineWeight(iLineWeight, (Autodesk.Revit.DB.GraphicsStyleType)1);
					transaction.Commit();
				}
				catch (Exception)
				{
					if (transaction != null && transaction.HasStarted() && !transaction.HasEnded())
					{
						transaction.RollBack();
					}
					return null;
				}
			}
			foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(GraphicsStyle)))
			{
				GraphicsStyle graphicsStyle = element as GraphicsStyle;
				if (graphicsStyle != null && graphicsStyle.Name.CompareTo(strLineTypeName) == 0)
				{
					return graphicsStyle;
				}
			}
			return null;
		}

		public static List<Element> GetDocCategoryElems(Autodesk.Revit.DB.Document doc, BuiltInCategory category)
		{
			List<Element> list = new List<Element>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc, doc.ActiveView.Id);
			filteredElementCollector.OfCategory(category).WhereElementIsNotElementType();
			foreach (Element item in filteredElementCollector)
			{
				list.Add(item);
			}
			return list;
		}

		public static List<DetailCurve> CreateLightingPos(Autodesk.Revit.DB.Document doc, XYZ pt)
		{
			List<DetailCurve> list = new List<DetailCurve>();
            Autodesk.Revit.DB.Color color = new Autodesk.Revit.DB.Color(0, byte.MaxValue, 0);
			GraphicsStyle lineStyle = Common.GetLineStyle(doc, "LightingPos", color, 5);
			Arc cv = Arc.Create(UnifiedModified.CreatePlane(XYZ.BasisZ, pt), 1.6404199475065617, 0.0, Math.PI*2);
			DetailCurve item = Common.AddDetailCurve2View(doc, cv, lineStyle, null);
			list.Add(item);
			return list;
		}

		public static FamilyInstance CreateLightingFamilyInstance(Autodesk.Revit.DB.Document doc, XYZ pt, double dAng, FamilySymbol symbol)
		{
			Transaction transaction = new Transaction(doc, "CreateFamilyInstance");
			try
			{
				transaction.Start();
				XYZ xyz = new XYZ(pt.X, pt.Y, Common.GetConfigLightElev(doc));
				FamilyInstance familyInstance = YJKRevitTools.LayFamilySymbol(doc, xyz, symbol, doc.ActiveView.GenLevel, dAng * 180.0 / Math.PI);
				try
				{
					double num = UnitConvert.CovertToAPI(28.0, (Autodesk.Revit.DB.DisplayUnitType)39);
					familyInstance.GetParameter("功率").Set(num);
					familyInstance.GetParameter("光源数量").Set(1);
					familyInstance.GetParameter("光源光通量").Set("2500");
				}
				catch (Exception)
				{
				}
				transaction.Commit();
				return familyInstance;
			}
			catch
			{
				transaction.RollBack();
			}
			return null;
		}

		public static List<Line> ConvertArc2Lines(Arc geArc)
		{
			List<Line> list = new List<Line>();
			try
			{
				double endParameter = geArc.GetEndParameter(0);
				double endParameter2 = geArc.GetEndParameter(1);
				XYZ endPoint = geArc.GetEndPoint(0);
				XYZ endPoint2 = geArc.GetEndPoint(1);
				Transform transform = geArc.ComputeDerivatives(endParameter, false);
				Transform transform2 = geArc.ComputeDerivatives(endParameter2, false);
				Curve curve = Line.CreateUnbound(endPoint, transform.BasisX);
				Line line = Line.CreateUnbound(endPoint2, transform2.BasisX);
				IntersectionResultArray intersectionResultArray = null;
				if ((int)curve.Intersect(line, out intersectionResultArray) == 8)
				{
					XYZ xyzpoint = intersectionResultArray.get_Item(0).XYZPoint;
					list.Add(Line.CreateBound(xyzpoint, endPoint));
					list.Add(Line.CreateBound(xyzpoint, endPoint2));
				}
			}
			catch
			{
			}
			return list;
		}

		public static List<Line> CombineEqualLines(List<Line> lstCvs)
		{
			List<Line> list = new List<Line>();
			int count = lstCvs.Count;
			for (int i = 0; i < count; i++)
			{
				Line line = lstCvs[i].Clone() as Line;
				line.MakeUnbound();
				bool flag = false;
				foreach (Line line2 in list)
				{
					XYZ endPoint = line2.GetEndPoint(0);
					XYZ endPoint2 = line2.GetEndPoint(1);
					if (line.Project(endPoint).Distance <= 0.1 && line.Project(endPoint2).Distance <= 0.1)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					List<CurveParamPoint> list2 = new List<CurveParamPoint>();
					for (int j = i; j < count; j++)
					{
						Line line3 = lstCvs[j];
						XYZ endPoint3 = line3.GetEndPoint(0);
						IntersectionResult intersectionResult = line.Project(endPoint3);
						if (intersectionResult.Distance <= 0.1)
						{
							list2.Add(new CurveParamPoint(intersectionResult.XYZPoint)
							{
								ParamOnCurve = intersectionResult.Parameter
							});
						}
						XYZ endPoint4 = line3.GetEndPoint(1);
						IntersectionResult intersectionResult2 = line.Project(endPoint4);
						if (intersectionResult2.Distance <= 0.1)
						{
							list2.Add(new CurveParamPoint(intersectionResult2.XYZPoint)
							{
								ParamOnCurve = intersectionResult2.Parameter
							});
						}
					}
					list2.Sort(new CurveParamPointComparer());
					Line item = Line.CreateBound(list2[0], list2[list2.Count - 1]);
					list.Add(item);
				}
			}
			return list;
		}

		public static double mmToFeet(double mm)
		{
			return mm * 0.0032808399;
		}

		public static XYZ Centroid(List<Curve> curveArray)
		{
			List<XYZ> list = new List<XYZ>();
			foreach (Curve curve in curveArray)
			{
				IList<XYZ> list2 = curve.Tessellate();
				for (int i = 0; i < list2.Count - 1; i++)
				{
					list.Add(list2[i]);
				}
			}
			double num = 0.0;
			double num2 = 0.0;
			double num3 = 0.0;
			int count = list.Count;
			for (int j = 0; j < count - 1; j++)
			{
				num += (list[j].X * list[j + 1].Y - list[j + 1].X * list[j].Y) / 2.0;
				num2 += (list[j].X * list[j + 1].Y - list[j + 1].X * list[j].Y) * (list[j].X + list[j + 1].X);
				num3 += (list[j].X * list[j + 1].Y - list[j + 1].X * list[j].Y) * (list[j].Y + list[j + 1].Y);
			}
			num += (list[count - 1].X * list[0].Y - list[0].X * list[count - 1].Y) / 2.0;
			num2 += (list[count - 1].X * list[0].Y - list[0].X * list[count - 1].Y) * (list[count - 1].X + list[0].X);
			num3 += (list[count - 1].X * list[0].Y - list[0].X * list[count - 1].Y) * (list[count - 1].Y + list[0].Y);
			num2 /= 6.0 * num;
			num3 /= 6.0 * num;
			return new XYZ(num2, num3, list[0].Z);
		}

		public static XYZ GetProjectPointByPlane(XYZ ptTest, Plane pl)
		{
			XYZ xyz = Transform.CreateReflection(pl).OfPoint(ptTest);
			return (ptTest + xyz) * 0.5;
		}

		public static Curve GetProjectCurveByPlane(Curve cvTest, Plane pl)
		{
			if (!cvTest.IsBound)
			{
				return null;
			}
			XYZ endPoint = cvTest.GetEndPoint(0);
			XYZ endPoint2 = cvTest.GetEndPoint(1);
			XYZ projectPointByPlane = Common.GetProjectPointByPlane(endPoint, pl);
			XYZ projectPointByPlane2 = Common.GetProjectPointByPlane(endPoint2, pl);
			if (cvTest is Line)
			{
				return Line.CreateBound(projectPointByPlane, projectPointByPlane2);
			}
			if (cvTest is Arc)
			{
				double endParameter = cvTest.GetEndParameter(0);
				double endParameter2 = cvTest.GetEndParameter(1);
				XYZ xyz = cvTest.Evaluate((endParameter + endParameter2) * 0.5, false);
				xyz = Common.GetProjectPointByPlane(xyz, pl);
				return Arc.Create(projectPointByPlane, projectPointByPlane2, xyz);
			}
			return null;
		}

		public static Document GetLinkedDocByCurDoc(Autodesk.Revit.DB.Document docCur, string strKeyStrInPathName)
		{
			string linkDocPathByStr = LinkDocumentOperator.GetLinkDocPathByStr(docCur, strKeyStrInPathName);
			foreach (Autodesk.Revit.DB.Document document in Common.GetLinkDocs(docCur))
			{
				if (string.Compare(document.PathName, linkDocPathByStr, false) == 0)
				{
					return document;
				}
			}
			return null;
		}

		public static List<Document> GetLinkDocs(Autodesk.Revit.DB.Document doc)
		{
			List<Document> list = new List<Document>();
			try
			{
				foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(RevitLinkInstance)))
				{
					RevitLinkInstance revitLinkInstance = (RevitLinkInstance)element;
					if (revitLinkInstance.GetLinkDocument() != null)
					{
						list.Add(revitLinkInstance.GetLinkDocument());
					}
				}
			}
			catch
			{
			}
			return list;
		}

		public static LightCfgData GetConfigData()
		{
			LightCfgData lightCfgData = new LightCfgData();
			try
			{
				string path = Path.GetTempPath() + "LightingLayoutConfigDlg.dat";
				if (!File.Exists(path))
				{
					throw new Exception("");
				}
				FileStream fileStream = new FileStream(path, FileMode.Open);
				StreamReader streamReader = new StreamReader(fileStream);
				streamReader.BaseStream.Seek(0L, SeekOrigin.Begin);
				lightCfgData.m_dLightElev = Convert.ToDouble(streamReader.ReadLine());
				lightCfgData.m_dBeamLaneA = Convert.ToDouble(streamReader.ReadLine());
				lightCfgData.m_dBeamLaneB = Convert.ToDouble(streamReader.ReadLine());
				lightCfgData.m_dBeamLaneC = Convert.ToDouble(streamReader.ReadLine());
				lightCfgData.m_dBeamLaneD = Convert.ToDouble(streamReader.ReadLine());
				lightCfgData.m_nBeamLightNums = Convert.ToUInt16(streamReader.ReadLine());
				lightCfgData.m_dGridLaneA = Convert.ToDouble(streamReader.ReadLine());
				lightCfgData.m_dGridLaneB = Convert.ToDouble(streamReader.ReadLine());
				lightCfgData.m_dGridLaneC = Convert.ToDouble(streamReader.ReadLine());
				lightCfgData.m_dGridLaneD = Convert.ToDouble(streamReader.ReadLine());
				lightCfgData.m_nGridLightNums = Convert.ToUInt16(streamReader.ReadLine());
				streamReader.Close();
				fileStream.Close();
			}
			catch
			{
				lightCfgData.m_dLightElev = 2500.0;
				lightCfgData.m_dBeamLaneA = 1500.0;
				lightCfgData.m_dBeamLaneB = 5300.0;
				lightCfgData.m_dBeamLaneC = 7800.0;
				lightCfgData.m_dBeamLaneD = 8400.0;
				lightCfgData.m_nBeamLightNums = 3;
				lightCfgData.m_dGridLaneA = 1500.0;
				lightCfgData.m_dGridLaneB = 5300.0;
				lightCfgData.m_dGridLaneC = 7800.0;
				lightCfgData.m_dGridLaneD = 8400.0;
				lightCfgData.m_nGridLightNums = 3;
			}
			return lightCfgData;
		}

		public static double GetConfigLightElev(Autodesk.Revit.DB.Document doc)
		{
			HVACUserSetting hvacuserSetting = new HVACUserSetting();
			new GarageLineParam();
			double num = double.Parse(hvacuserSetting.GetGarageInterFaceInfo().InstallOffset);
			Level genLevel = doc.ActiveView.GenLevel;
			return num * 1000.0 / 304.8;
		}

		public static ushort RoomIllumCalcLampCount(double dRoomArea, double dIllumStandard, double dIllumFlex, double dUserFactor, double dLLF)
		{
			return (ushort)Math.Ceiling(dIllumStandard * dRoomArea / (dIllumFlex * dUserFactor * dLLF));
		}

		public static FamilySymbol GetHYBimspaceLightingFamilySymbol(Autodesk.Revit.DB.Document doc)
		{
			FamilySymbol result = null;
			DbFamilyObject dbFamilyObject = null;
			foreach (DbFamilyObject dbFamilyObject2 in Common.GetLampInfoData(doc))
			{
				if (dbFamilyObject2.ToString() == Common.m_strLightingFamilyName)
				{
					dbFamilyObject = dbFamilyObject2;
					break;
				}
			}
			if (dbFamilyObject != null)
			{
				result = HYFamilyUtils.FamilySymbol(doc, dbFamilyObject.Family, (Autodesk.Revit.DB.BuiltInCategory)(-2001120));
			}
			return result;
		}

		public static List<DbFamilyObject> GetLampInfoData(Autodesk.Revit.DB.Document doc)
		{
			return new FamilyLibDataAssist(doc, Common.strDBTableName).LoadFamilyDatas(null);
		}

		public static string strDBTableName = "Lamp";

		public static string m_strLightingFamilyName = "单管荧光灯_悬挂";
	}
}
